package com.example.demo.config;

import java.util.Objects;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.BaseCodec;
import org.redisson.client.codec.Codec;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;


import io.netty.channel.nio.NioEventLoopGroup;

/**
 * redission配置信息加载
 *
 * @author lixiaodong
 */
@Configuration
@PropertySource("classpath:application-ha.properties")
class RedissonConfig {
    @Value("${ha.spring.redisson.address:redis://127.0.0.1:6379}")
    private String address;

    @Value("${ha.spring.redisson.connectionMinimumIdleSize:10}")
    private int connectionMinimumIdleSize;

    @Value("${ha.spring.redisson.idleConnectionTimeout:10000}")
    private int idleConnectionTimeout;

    @Value("${ha.spring.redisson.connectTimeout:10000}")
    private int connectTimeout;

    @Value("${ha.spring.redisson.timeout:3000}")
    private int timeout;

    @Value("${ha.spring.redisson.retryAttempts:2}")
    private int retryAttempts;

    @Value("${ha.spring.redisson.retryInterval:1500}")
    private int retryInterval;

    @Value("${ha.spring.redisson.password:}")
    private String password;

    @Value("${ha.spring.redisson.connectionPoolSize:64}")
    private int connectionPoolSize;

    @Value("${ha.spring.redisson.database:0}")
    private int database;

    @Value("${ha.spring.redisson.codec:org.redisson.codec.FstCodec}")
    private String codec;

    @Bean(destroyMethod = "shutdown", name = "defaultRedisson")
    @Primary
    RedissonClient defaultCodecRedisson() throws Exception {
        return Redisson.create(getRedissonConfig(null));
    }

    @Bean(destroyMethod = "shutdown", name = "stringCodecRedisson")
    RedissonClient stringCodecRedisson() throws Exception {
        return Redisson.create(getRedissonConfig(new org.redisson.client.codec.StringCodec()));
    }

    private Config getRedissonConfig(BaseCodec codec) throws Exception {
        Config config = new Config();
        config.setCodec(getCodec());
        config.useSingleServer().setAddress(address)
                .setConnectionMinimumIdleSize(connectionMinimumIdleSize)
                .setConnectionPoolSize(connectionPoolSize)
                .setDatabase(database)
                .setRetryAttempts(retryAttempts)
                .setRetryInterval(retryInterval)
                .setTimeout(timeout)
                .setConnectTimeout(connectTimeout)
                .setIdleConnectionTimeout(idleConnectionTimeout)
                .setPassword("".equals(password) ? null : password);
        int threadCount = Runtime.getRuntime().availableProcessors() * 2 + 1;
        config.setThreads(threadCount);
        config.setEventLoopGroup(new NioEventLoopGroup());
        if (!Objects.isNull(codec)) {
            config.setCodec(codec);
        }
        return config;
    }

    private Codec getCodec() throws Exception {
        return (Codec) Class.forName(codec).newInstance();
    }
}
